home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Utilities / Programming / EnterAct 3.5 / Drag_on Modules / hAWK programs / $CompareFiles < prev    next >
Encoding:
Text File  |  1995-05-20  |  7.7 KB  |  316 lines  |  [TEXT/KEEN]

  1. # $CompareFiles: display mismatched lines from two files.
  2. #Usage
  3. #Use “MFS selected files” input option after selecting
  4. #the two files you wish to compare
  5. #Leave “Show stdout” selected
  6. #Recommended: do not adjust the variables
  7. #dynamic_minimum or constant_minimum unless you suspect the
  8. #comparison is faulty. In this case, first try
  9. #    dynamic_minimum=4
  10. #and if that doesn’t work, try
  11. #    constant_minimum=2 or more, whatever you think is needed.
  12. #
  13. #To do:
  14. #         -display mismatched lines in surrounding context
  15. #        -side-by-side display of mismatched lines
  16. #        -performance bogs down badly if mismatch > 50 lines
  17. #
  18.  
  19. ####### Nuisance miscompares due to just different spaces and tabs?
  20. # To ignore just white-space differences, search for the
  21. # two instances of "##gsub..." below and enable them by
  22. # deleting the "##" just before the gsub's.
  23.  
  24. #How it works:
  25. #This is a simple version of MPW’s “Compare” tool, implementation
  26. #here taken from the description in the MPW manual - note function
  27. #is not quite the same, but close. Lines are read from both files;
  28. #when a mismatch is encountered, lines are stacked up one at a time
  29. #from each file into the arrays s1[], s2[]. As each pair of lines is
  30. #added, the arrays s1 and s2 are checked for a group of lines that
  31. #matches up again. This group must be “G” lines long, where G is either
  32. #calculated from a formula or set to the constant value “constant_minimum”,
  33. #if that variable has been set with the setup dialog. A minimum value may
  34. #also be set if G is calculated, by setting the value of “dynamic_minimum”
  35. #in the setup dialog. The formula used to calculate G is
  36. #    G = int((2*log(M)/c10)+2)
  37. #where M is the number of lines in s1[] (or s2[]) and
  38. #    c10 = log(10), ie we’re doing the logs base 10.
  39. #Note the minimum calculated value of G is 2, and it increases very slowly.
  40. #
  41. #Variables:
  42. #Name                use
  43. #-----                ------------------------------------------------------
  44. #dynamic_minimum    when G is calculated, this is used as minimum
  45. #                        value; default minimum is 2
  46. #constant_minimum    used as the fixed value for G instead of calculating it
  47. #                        - minimum value is 2 if it is not zero.
  48. #(For default operation, leave both dynamic_minimum=0
  49. #and constant_minimum=0.)
  50. #
  51. #Illustrates:
  52. #-dispensing with the default input retrieval, doing it with getline
  53. #(in fact, reading from two files at once).
  54. #-how to get lines from file, or temporary buffer if lines have already
  55. #been read in, gory details isolated in “GetNextLine()”.
  56. #-top down structured approach - note the only pattern/action is the
  57. #BEGIN block, everything important is done with functions.
  58. #
  59. # User’s Manual references:
  60. # «hAWK User’s Manual» «F   Running hAWK programs»
  61. # «hAWK User’s Manual» «L  5   Regular expressions»
  62. # «hAWK User’s Manual» «M  5   Built-in string and file functions»
  63. # «hAWK User’s Manual» «K  4   Built-in variables»
  64. # «hAWK User’s Manual» «K  8   Arrays»
  65. # «hAWK User’s Manual» «N   User-defined functions»
  66. # «hAWK User’s Manual» «P  3   The getline function»
  67. # «hAWK User’s Manual» «O  3   Output into files»
  68. # «hAWK User’s Manual» «Q   The hAWK function»
  69.  
  70. BEGIN { if (ARGC != 3)
  71.             {
  72.             print "Two files at a time, please"
  73.             exit
  74.             }
  75.         file1 = ARGV[1]
  76.         file2 = ARGV[2]
  77.         z1 = split(ARGV[1], names1, ":")
  78.         z2 = split(ARGV[2], names2, ":")
  79.         c10 = log(10)
  80.         #G = int((2*log(M)/c10)+2)
  81.         if (constant_minimum+0 != 0 && constant_minimum+0 < 2)
  82.             constant_minimum = 2
  83.         if (constant_minimum+0 > 0)
  84.             MMAX = 50
  85.         else
  86.             MMAX = 1000
  87.         CompareFiles();
  88.     }
  89.  
  90. function CompareFiles()
  91.     {
  92.     print "Comparison of", file1, "(first file)"
  93.     print "with", file2, "(second file):"
  94.     print ""
  95.     while (GetNextLines())
  96.         {
  97.         ++FNR1; ++FNR2;
  98.         if (x1 != x2)
  99.             {
  100.             anyMisMatch = 1
  101.             Resynch()
  102.             }
  103.         }
  104.     if (EOF1)
  105.         {
  106.         if ((getline x2 < file2) > 0)
  107.             {
  108.             #first file ran out, second keeps going...
  109.             anyMisMatch = 1
  110.             print "----------Extra lines at end of second file at", names2[z2], FNR2
  111.             do
  112.                 {
  113.                 print x2;
  114.                 } while ((getline x2 < file2) > 0);
  115.             }
  116.         }
  117.     else #EOF2, and implied miscompare since EOF1 not true
  118.         {
  119.         anyMisMatch = 1
  120.         print "----------Extra lines at end of first file at", names1[z1], FNR1
  121.         do
  122.             {
  123.             print x1;
  124.             } while ((getline x1 < file1) > 0);
  125.         }
  126.     if (anyMisMatch == 0)
  127.         print "----------files match completely."
  128.     }
  129.  
  130. function GetNextLines()
  131.     {
  132.     if (t1Next < t1Max)
  133.         {
  134.         x1 = t1[++t1Next]
  135.         delete t1[t1Next]
  136.         }
  137.     else
  138.         {
  139.         if ((getline x1 < file1) <= 0)
  140.             {
  141.             EOF1 = 1
  142.             return 0
  143.             }
  144.         ##gsub(/[ \t]+/, "", x1);##enable this to ignore white space differences
  145.         }
  146.     
  147.     if (t2Next < t2Max)
  148.         {
  149.         x2 = t2[++t2Next]
  150.         delete t2[t2Next]
  151.         }
  152.     else
  153.         {
  154.         if ((getline x2 < file2) <= 0)
  155.             {
  156.             EOF2 = 1
  157.             return 0
  158.             }
  159.         ##gsub(/[ \t]+/, "", x2);##enable this to ignore white space differences
  160.         }
  161.     
  162.     return 1
  163.     }
  164.  
  165. function Resynch()
  166.     {
  167.     s1[1] = x1
  168.     s2[1] = x2
  169.     M = 1
  170.     do
  171.         {
  172.         if (!GetNextLines())
  173.             {
  174.             if (EOF1)
  175.                 {
  176.                 print "!!!End of first file, ", names1[z1]
  177.                 print "encountered during mismatched section."
  178.                 PrintMiscompare();
  179.                 exit
  180.                 }
  181.             else
  182.                 {
  183.                 print "!!!End of second file, ", names2[z2]
  184.                 print "encountered during mismatched section."
  185.                 PrintMiscompare();
  186.                 exit
  187.                 }
  188.             }
  189.         s1[++M] = x1
  190.         s2[M] = x2
  191.         } while (!GroupMatch() && M <= MMAX);
  192.     if (M > MMAX)
  193.         {
  194.         print "!!!Mismatch over", MMAX, "lines, quitting early."
  195.         exit
  196.         }
  197.     #Group match - print out miscompare
  198.     PrintMiscompare();
  199.     }
  200.  
  201. function GroupMatch()
  202.     {
  203.     if (constant_minimum+0 > 0)
  204.         G = constant_minimum
  205.     else
  206.         {
  207.         G = int((2*log(M)/c10)+2)
  208.         if (G < dynamic_minimum+0)
  209.             G = dynamic_minimum
  210.         }
  211.     #Attempt to match last G lines of s1 against s2
  212.     #-start from beginning of s2
  213.     GMinus = M-G+1
  214.     for (i = 1; i <= GMinus; ++i)
  215.         {
  216.         while (i <= GMinus && s1[GMinus] != s2[i])
  217.             ++i;
  218.         if (i <= GMinus)
  219.             {
  220.             j = i + 1
  221.             numMatched = 1
  222.             while (s1[GMinus + numMatched] == s2[j] &&
  223.                 ++numMatched < G && j <= M)
  224.                 ++j;
  225.             if (numMatched == G)
  226.                 {
  227.                 s1First = GMinus
  228.                 s2First = i
  229.                 return 1
  230.                 }
  231.             }
  232.         }
  233.     #Attempt to match last G lines of s2 against s1
  234.     #-start from beginning of s1
  235.     for (i = 1; i <= GMinus; ++i)
  236.         {
  237.         while (i <= GMinus && s2[GMinus] != s1[i])
  238.             ++i;
  239.         if (i <= GMinus)
  240.             {
  241.             j = i + 1
  242.             numMatched = 1
  243.             while (s2[GMinus + numMatched] == s1[j] &&
  244.                 ++numMatched < G && j <= M)
  245.                 ++j;
  246.             if (numMatched == G)
  247.                 {
  248.                 s2First = GMinus
  249.                 s1First = i
  250.                 return 1
  251.                 }
  252.             }
  253.         }
  254.     return 0
  255.     }
  256.  
  257. #Lines added to one file is same as lines deleted from other file
  258. #If match doesn't start at beginning of one buffer, then print
  259. #mismatching lines from beginnings of both buffers
  260. function PrintMiscompare()
  261.     {
  262.     print "------------------------------------------------------------------------"
  263.     if (s1First == 1)
  264.         {
  265.         print "----------Extra lines in second file at", names2[z2], FNR2, " (vs", names1[z1], FNR1, ")"
  266.         for (i = 1; i < s2First; ++i)
  267.             print s2[i]
  268.         
  269.         }
  270.     else if (s2First == 1)
  271.         {
  272.         print "----------Extra lines in first file at", names1[z1], FNR1,  " (vs", names2[z2], FNR2, ")"
  273.         for (i = 1; i < s1First; ++i)
  274.             print s1[i]
  275.         }
  276.     else
  277.         {
  278.         print "----------Mismatching lines in both files:"
  279.         print "----------from first file at",  names1[z1], FNR1
  280.         for (i = 1; i < s1First; ++i)
  281.             print s1[i]
  282.         print "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
  283.         print "----------from second file at",  names2[z2], FNR2
  284.         for (i = 1; i < s2First; ++i)
  285.             print s2[i]
  286.         }
  287.     print "------------------------------------------------------------------------"
  288.     print ""
  289.     s1First += G
  290.     s2First += G
  291.     FNR1 += s1First - 2
  292.     FNR2 += s2First - 2
  293.     if (s1First <= M)
  294.         {
  295.         j = t1Max;
  296.         for (i = s1First; i <= M; ++i)
  297.             {
  298.             t1[++j] = s1[i]
  299.             }
  300.         t1Max = j
  301.         }
  302.     if (s2First <= M)
  303.         {
  304.         j = t2Max
  305.         for (i = s2First; i <= M; ++i)
  306.             {
  307.             t2[++j] = s2[i]
  308.             }
  309.         t2Max = j
  310.         }
  311.     for (i in s1)
  312.         delete s1[i]
  313.     for (i in s2)
  314.         delete s2[i]
  315.     }
  316.